package com.pdg.mcplugin.varnish;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.bukkit.Material;
import org.bukkit.TreeSpecies;
import org.bukkit.block.Block;
import org.bukkit.block.Chest;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;

import com.pdg.mcplugin.common.PlayerUtilities;
import com.pdg.mcplugin.common.baseclasses.PluginClientBase;

public class VarnishEventListener extends PluginClientBase<Varnish> implements Listener{

	private static final String NOTHING_STAINED = "Nothing was stained.";
	private static final String STAINED_RESULT_FORMAT = "Number of items stained: %d. Number of units of dye used: %d.";
	private static final String BLEACHED_RESULT_FORMAT = "Number of items bleached: %d. Number of units of dye used: %d.";
	private static final String NOTHING_BLEACHED = "Nothing was bleached.";

	public VarnishEventListener(Varnish thePlugin) {
		super(thePlugin);
	}
	
	@EventHandler
	public void onPlayerInteract(PlayerInteractEvent event){
		//has to be a right click
		//has to have an item involved
		//has to have a block involved
		if(event.getAction()==Action.RIGHT_CLICK_BLOCK && event.hasItem() && event.hasBlock()){
			Player thePlayer = event.getPlayer();
			//player has to be sneaking
			if(thePlayer.isSneaking()){
				Block theBlock = event.getClickedBlock();
				//has to be a chest
				if(theBlock.getType() == Material.CHEST){
					Chest theChest = (Chest)theBlock.getState();
					ItemStack theItemStack = event.getItem();
					//has to be dye
					MaterialData theMaterialData = theItemStack.getData();
					if(theMaterialData.getItemType()==Material.INK_SACK){
						if(theMaterialData.getData()==RecipeMaker.WHITE_DYE.getData()){
							bleachWoodItems(thePlayer,theChest);
							event.setCancelled(true);
						}else if(theMaterialData.getData()==RecipeMaker.BROWN_DYE.getData()){
							stainWoodItems(thePlayer,theChest);
							event.setCancelled(true);
						}
					}
				}
			}
		}
	}

	private void stainWoodItems(Player thePlayer, Chest theChest) {
		int theDyeCount = PlayerUtilities.getPlayerItemCount(thePlayer,RecipeMaker.BROWN_DYE);
		int theTotalStained = 0;
		int theDyeUsed = 0;
		List<ItemStack> removeItems = new ArrayList<ItemStack>();
		List<ItemStack> addItems = new ArrayList<ItemStack>();
		Iterator<ItemStack> iterator = theChest.getInventory().iterator();
		while(iterator.hasNext()){
			ItemStack theItemStack = iterator.next();
			if(theItemStack==null) continue;
			Material theSourceMaterial = theItemStack.getData().getItemType();
			byte theSourceData = theItemStack.getData().getData();
			Material theFinalMaterial = theSourceMaterial;
			byte theFinalData = theSourceData;
			if(!getBatchStainFeature(theSourceMaterial)){
				continue;
			}
			switch(theSourceMaterial){
			case WOOD:
			case WOOD_STEP:
				switch(TreeSpecies.getByData(theSourceData)){
				case BIRCH:
					theFinalData = TreeSpecies.GENERIC.getData();
					break;
				case GENERIC:
					theFinalData = TreeSpecies.JUNGLE.getData();
					break;
				case JUNGLE:
					theFinalData = TreeSpecies.REDWOOD.getData();
					break;
				default:
					break;
				}
				break;
			case BIRCH_WOOD_STAIRS:
				theFinalMaterial = Material.WOOD_STAIRS;
				break;
			case WOOD_STAIRS:
				theFinalMaterial = Material.JUNGLE_WOOD_STAIRS;
				break;
			case JUNGLE_WOOD_STAIRS:
				theFinalMaterial = Material.SPRUCE_WOOD_STAIRS;
				break;
			default:
				break;
			}
			if(theSourceMaterial!=theFinalMaterial || theSourceData!=theFinalData){
				int theAmount = theItemStack.getAmount();
				int theDyeCost = (theAmount + RecipeMaker.MAXIMUM_COUNT-1) / RecipeMaker.MAXIMUM_COUNT;
				if(theDyeCost<=theDyeCount){
					theDyeUsed += theDyeCost;
					theDyeCount -= theDyeCost;
					theTotalStained += theAmount;
					removeItems.add(theItemStack);
					addItems.add(new MaterialData(theFinalMaterial,theFinalData).toItemStack(theItemStack.getAmount()));
				}
			}
		}
		if(theTotalStained>0){
			getPlugin().sendSuccessMessage(thePlayer, String.format(STAINED_RESULT_FORMAT, theTotalStained, theDyeUsed));
			PlayerUtilities.removePlayerItemCount(thePlayer,RecipeMaker.BROWN_DYE,theDyeUsed);
			iterator = removeItems.iterator();
			while(iterator.hasNext()){
				ItemStack theItemStack = iterator.next();
				theChest.getInventory().remove(theItemStack);
			}
			iterator = addItems.iterator();
			while(iterator.hasNext()){
				ItemStack theItemStack = iterator.next();
				theChest.getInventory().addItem(theItemStack);
			}
			theChest.update();
		}else{
			getPlugin().sendErrorMessage(thePlayer, NOTHING_STAINED);
		}
	}

	private boolean getBatchStainFeature(Material theSourceMaterial) {
		switch(theSourceMaterial){
		case WOOD:
			return getPlugin().getFeatureManager().getFeature(VarnishFeatures.BATCH_STAIN_PLANKS);
		case WOOD_STEP:
			return getPlugin().getFeatureManager().getFeature(VarnishFeatures.BATCH_STAIN_STEPS);
		case SPRUCE_WOOD_STAIRS:
		case JUNGLE_WOOD_STAIRS:
		case WOOD_STAIRS:
			return getPlugin().getFeatureManager().getFeature(VarnishFeatures.BATCH_STAIN_STAIRS);
		default:
			return false;
		}
	}

	private void bleachWoodItems(Player thePlayer, Chest theChest) {
		int theDyeCount = PlayerUtilities.getPlayerItemCount(thePlayer,RecipeMaker.WHITE_DYE);
		int theTotalStained = 0;
		int theDyeUsed = 0;
		List<ItemStack> removeItems = new ArrayList<ItemStack>();
		List<ItemStack> addItems = new ArrayList<ItemStack>();
		Iterator<ItemStack> iterator = theChest.getInventory().iterator();
		while(iterator.hasNext()){
			ItemStack theItemStack = iterator.next();
			if(theItemStack==null) continue;
			Material theSourceMaterial = theItemStack.getData().getItemType();
			byte theSourceData = theItemStack.getData().getData();
			Material theFinalMaterial = theSourceMaterial;
			byte theFinalData = theSourceData;
			if(!getBatchBleachFeature(theSourceMaterial)){
				continue;
			}
			switch(theSourceMaterial){
			case WOOD:
			case WOOD_STEP:
				switch(TreeSpecies.getByData(theSourceData)){
				case REDWOOD:
					theFinalData = TreeSpecies.JUNGLE.getData();
					break;
				case JUNGLE:
					theFinalData = TreeSpecies.GENERIC.getData();
					break;
				case GENERIC:
					theFinalData = TreeSpecies.BIRCH.getData();
					break;
				default:
					break;
				}
				break;
			case SPRUCE_WOOD_STAIRS:
				theFinalMaterial = Material.JUNGLE_WOOD_STAIRS;
				break;
			case JUNGLE_WOOD_STAIRS:
				theFinalMaterial = Material.WOOD_STAIRS;
				break;
			case WOOD_STAIRS:
				theFinalMaterial = Material.BIRCH_WOOD_STAIRS;
				break;
			default:
				break;
			}
			if(theSourceMaterial!=theFinalMaterial || theSourceData!=theFinalData){
				int theAmount = theItemStack.getAmount();
				int theDyeCost = (theAmount + RecipeMaker.MAXIMUM_COUNT-1) / RecipeMaker.MAXIMUM_COUNT;
				if(theDyeCost<=theDyeCount){
					theDyeUsed += theDyeCost;
					theDyeCount -= theDyeCost;
					theTotalStained += theAmount;
					removeItems.add(theItemStack);
					addItems.add(new MaterialData(theFinalMaterial,theFinalData).toItemStack(theItemStack.getAmount()));
				}
			}
		}
		if(theTotalStained>0){
			getPlugin().sendSuccessMessage(thePlayer, String.format(BLEACHED_RESULT_FORMAT, theTotalStained, theDyeUsed));
			PlayerUtilities.removePlayerItemCount(thePlayer,RecipeMaker.WHITE_DYE,theDyeUsed);
			iterator = removeItems.iterator();
			while(iterator.hasNext()){
				ItemStack theItemStack = iterator.next();
				theChest.getInventory().remove(theItemStack);
			}
			iterator = addItems.iterator();
			while(iterator.hasNext()){
				ItemStack theItemStack = iterator.next();
				theChest.getInventory().addItem(theItemStack);
			}
			theChest.update();
		}else{
			getPlugin().sendErrorMessage(thePlayer, NOTHING_BLEACHED);
		}
	}

	private boolean getBatchBleachFeature(Material theSourceMaterial) {
		switch(theSourceMaterial){
		case WOOD:
			return getPlugin().getFeatureManager().getFeature(VarnishFeatures.BATCH_BLEACH_PLANKS);
		case WOOD_STEP:
			return getPlugin().getFeatureManager().getFeature(VarnishFeatures.BATCH_BLEACH_STEPS);
		case JUNGLE_WOOD_STAIRS:
		case WOOD_STAIRS:
		case BIRCH_WOOD_STAIRS:
			return getPlugin().getFeatureManager().getFeature(VarnishFeatures.BATCH_BLEACH_STAIRS);
		default:
			return false;
		}
	}
}
